package cz.muni.fi.pa165.soccergamesarchive.businesslayer.services;

import cz.muni.fi.pa165.soccergamesarchive.businesslayer.dtos.SoccerMatchDTO;
import cz.muni.fi.pa165.soccergamesarchive.businesslayer.dtos.SoccerMatchHeaderDTO;
import cz.muni.fi.pa165.soccergamesarchive.errorhandling.ErrorHandler;
import cz.muni.fi.pa165.soccergamesarchive.persistencelayer.daos.SoccerMatchDAO;
import cz.muni.fi.pa165.soccergamesarchive.persistencelayer.entities.SoccerMatch;
import cz.muni.fi.pa165.soccergamesarchive.validators.ValidatorTest;
import java.util.Date;
import java.util.List;
import java.util.Map;
import javax.annotation.security.DeclareRoles;
import javax.annotation.security.RolesAllowed;
import javax.ejb.EJB;
import javax.ejb.Stateless;
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;

import static cz.muni.fi.pa165.soccergamesarchive.errorhandling.ErrorHandler.createErrorMessage;
import static cz.muni.fi.pa165.soccergamesarchive.utils.EntityDTOTransformer.transform;
import static cz.muni.fi.pa165.soccergamesarchive.utils.EntityDTOTransformer.transformList;
import static cz.muni.fi.pa165.soccergamesarchive.validators.SoccerMatchValidator.validate;

/**
 *
 * @author Ondrej Dubovec <dubovec.ondrej@gmail.com>
 *
 * <strong>EDITED BY: Michal Ďuriš</strong>
 */
@DeclareRoles("Archiver")
@Stateless(name = "SoccerMatchService")
public class SoccerMatchServiceBean implements SoccerMatchServiceBeanLocal {

    @EJB
    private SoccerMatchDAO dao;

    public void setDao(SoccerMatchDAO dao) {
        this.dao = dao;
    }

    public SoccerMatchDAO getDao() {
        return this.dao;
    }

    @TransactionAttribute(TransactionAttributeType.REQUIRED)
    @RolesAllowed("Archiver")
    @Override
    public SoccerMatchDTO addSoccerMatch(SoccerMatchDTO soccerMatchDTO) throws
            RuntimeException {
        SoccerMatch match = transform(soccerMatchDTO,
                SoccerMatch.class);
        validate(match, ValidatorTest.NULL_TEST,
                ValidatorTest.CORRECT_RECORD_TEST);
        match = dao.addSoccerMatch(match);
        return transform(match, SoccerMatchDTO.class);
    }

    @TransactionAttribute(TransactionAttributeType.REQUIRED)
    @RolesAllowed("Archiver")
    @Override
    public SoccerMatchDTO changeSoccerMatch(SoccerMatchDTO soccerMatchDTO)
            throws RuntimeException {
        SoccerMatch match = transform(
                soccerMatchDTO, SoccerMatch.class);
        validate(match, ValidatorTest.FULL_TEST);
        match = dao.changeSoccerMatch(match);
        return transform(match, SoccerMatchDTO.class);
    }

    @TransactionAttribute(TransactionAttributeType.REQUIRED)
    @RolesAllowed("Archiver")
    @Override
    public void deleteSoccerMatch(SoccerMatchDTO soccerMatchDTO) throws
            RuntimeException {
        SoccerMatch match = transform(soccerMatchDTO,
                SoccerMatch.class);
        validate(match, ValidatorTest.NULL_TEST);
        dao.deleteSoccerMatch(match);
    }

    @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
    @Override
    public List<SoccerMatchDTO> getAllSoccerMatches() throws RuntimeException {
        List<SoccerMatch> matches = dao.getAllSoccerMatches();
        return transformList(matches, SoccerMatchDTO.class);
    }

    @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
    @Override
    public List<SoccerMatchDTO> getLimitedNumberOfMatches(int offset, int limit,
                                                          Map<String, Object> filterMap,
                                                          Map<String, Boolean> orderMap)
            throws RuntimeException {
        
        if (offset < 0 || limit <= 0) {
            throw new IllegalArgumentException(createErrorMessage(
                    this.getClass().getName(), ErrorHandler.ILLEGAL_VALUE_ERROR));
        }
        
        List<SoccerMatch> matches = dao.getLimitedNumberOfMatches(offset, limit,
                filterMap, orderMap);

        return transformList(matches, SoccerMatchDTO.class);
    }

    @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
    @Override
    public List<SoccerMatchHeaderDTO> getLimitedNumberOfMatchHeaders(int offset,
                                                                     int limit,
                                                                     Map<String, Object> filterMap,
                                                                     Map<String, Boolean> orderMap)
            throws RuntimeException {

        if (offset < 0 || limit <= 0) {
            throw new IllegalArgumentException(createErrorMessage(
                    getClass().getName(), ErrorHandler.ILLEGAL_VALUE_ERROR));
        }

        return dao.getLimitedNumberOfMatchHeaders(offset, limit, filterMap,
                orderMap);
    }

    @Override
    public int getFilteredSoccerMatchesCount(Map<String, Object> filterMap)
            throws RuntimeException {

        return dao.getFilteredSoccerMatchesCount(filterMap);
    }

    @Override
    public int getFilteredMatchHeadersCount(Map<String, Object> filterMap)
            throws RuntimeException {

        return dao.getFilteredMatchHeadersCount(filterMap);
    }

    @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
    @Override
    public SoccerMatchDTO getSoccerMatchById(Long id) throws RuntimeException {
        if (id == null || id.intValue() < 1) {
            throw new IllegalArgumentException(createErrorMessage(
                    this.getClass().getName(), ErrorHandler.ILLEGAL_VALUE_ERROR));
        }

        SoccerMatch match = dao.getSoccerMatchById(id);

        return transform(match, SoccerMatchDTO.class);
    }

    @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
    @Override
    public List<SoccerMatchDTO> getSoccerMatchesByDate(Date date) throws
            RuntimeException {

        if (date == null) {
            throw new IllegalArgumentException(createErrorMessage(
                    getClass().getName(), ErrorHandler.ILLEGAL_VALUE_ERROR));
        }

        return transformList(dao.getSoccerMatchesByDate(
                date), SoccerMatchDTO.class);
    }

}
